java 编程思想

File类

file类名字具有一定的误导性,它既能代表一个特定文件的名称,又能代表一个目录下的一组文件的名称。如果指的是一个文件集,就可以对此集合调用list()方法。返回一个字符数组,如果想要取得不同目录列表,只需再创建一个不同的File对象。

File类不仅仅只代表存在的文件或目录。也可以用File对象来创建新的目录或尚不存在的整个目录路径。我们还可以查看文件的特性(如:大小,最后修改日期,读/写)检查某个File对象代表的是一个文件还是一个目录,并可以删除文件。

输入输出

有时我们必须把来自于“字节”层次结构中的类和“字符”层次结构中的类结合起来使用。为了实现这个目的,要用到“适配器”(adapter)类:InputStreamReader可以把InputStream转换为Reader,而OutputStreamWriter可以把OutputStream转换为Writer。

设计ReaderWriter继承层次结构主要是为了国际化。老的I/ O流继承层次结构仅支持8位字节流,并且不能很好地处理16位的Unicode字符。由于Unicode用于字符国际化(Java本身的char也是16位的Unicode),所以添加Reader和Writer继承层次结构就是为了在所有的I/O操作中都支持Unicode。另外,新类库的设计使得它的操作比旧类库更快。

底层原理

缓冲(缓存)处理

缓存处理是所有IO操作的基础,术语输入输出只对数据移入移出缓存有意义。

用户空间与内核空间对应内存中不同的位置划分。通常32位Linux内核地址空间划分0~3G为用户空间,3~4G为内核空间。用户空间与内核空间也可以进行内存共享,以避免大量的数据复制。

进程执行操作系统的I/O请求包括数据从缓冲区排出(写操作)和数据填充缓冲区(读操作)。

例如一个磁盘,移动到进程的存储区域(例如RAM)中。首先,进程要求其缓冲通过read()系统调用填满。这个系统调用导致内核向磁盘控制硬件发出一条命令要从磁盘获取数据。磁盘控制器通过DMA直接将数据写入内核的内存缓冲区,不需要主CPU进一步帮助。当请求read()操作时,一旦磁盘控制器完成了缓存的填写,内核从内核空间的临时缓存拷贝数据到进程指定的缓存中。

DMA技术的出现,使得外围设备可以通过DMA控制器直接访问内存,与此同时,CPU可以继续执行程序。DMA控制器获得总线控制权后,CPU即刻挂起或只执行内部操作,由DMA控制器输出读写命令,直接控制RAM与I/O接口进行DMA传输。

虚拟内存

虚拟内存计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换

之所以要从内核空间拷贝到最终用户空间而不直接从磁盘到用户空间是由于虚拟内存的存在。

通过将内核空间地址映射到相同的物理地址作为一个用户空间的虚拟地址。这个缓存同时对内核和用户空间进程可见。

close与flush

A:close()关闭流对象,但是先刷新一次缓冲区,关闭之后,流对象不可以继续再使用了。close()中会调用flush。
B:flush()仅仅是刷新缓冲区(一般写字符时要用,因为字符是先进入的缓冲区),流对象还可以继续使用

在io中,为了提高效率,通常是在缓存区满时进行一次读写,所以对于缓存区未满的情况下需要手动调用刷新将缓存区数据取出。

reader、writer与Stream

InputStream 是字节输入流的所有类的超类,一般我们使用它的子类,如FileInputStream等.一个byte一个byte的读。
InputStreamReader 是字节流通向字符流的桥梁,它将字节流转换为字符流.

bufferedwriter与filewriter的关系。


BufferedWriter
1.有缓冲区(默认8192字符=16384字节)可以通过构造方法来修改(一般不需修改)
2.由于有缓冲区所以效率要比FileWriter高
3.缓冲区能缓存8192个字符满了或者close、flush之后才会进行查码表之后再缓存在StreamEncoder的缓冲区中(8192字节)
4.内部是使用FileWriter来读写的
FileWriter
1.其实内部也有缓冲区(8192字节)
2.FileWriter效率低
3.来一个字符查一次码表缓冲在StreamEncoder的缓冲区中(8192字节)。

读写操作应该close的一个原因是其对文件操作会占用操作系统的文件描述符,操作系统的文件描述符有上限。